package com.sne.common.aspect;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sne.common.entity.Result;
import com.sne.common.util.IdGeneratorUtil;
import com.sne.sys.entity.SysLog;
import com.sne.sys.entity.SysLoginLog;
import com.sne.sys.entity.SysUser;
import com.sne.sys.service.ISysUserService;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录日志
 *
 * @author fanghh
 * @date 2020/11/12
 */
@Slf4j
@Component
@Aspect
public class SysLoginAspect {


    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private HttpServletRequest request;

    private final static String[] IPS = {"localhost", "127.0.0.1"};

    @Value("${baidu.ak}")
    private final static String IPAPI = "http://api.map.baidu.com/location/ip";

    /**
     * 异常
     */
    private static final String ERROR = "失败";

    /**
     * 正常
     */
    private static final String SUCCESS = "成功";

    @Pointcut(value = "execution(* com.sne.sys.controller.LoginController.login(..))")
    public void pointCut() {
    }

    @Transactional(rollbackFor = Exception.class)
    @AfterThrowing(value = "pointCut()", throwing = "e")
    public void afterTrowing(JoinPoint joinPoint, Throwable e) {
        String msg = "";
        if (e instanceof BadCredentialsException) {
            msg = "用户名或密码不正确";
        }
        saveLog(joinPoint, ERROR, Result.failed(e.getMessage(), msg));
    }

    @Transactional(rollbackFor = Exception.class)
    @AfterReturning(value = "pointCut()", returning = "value")
    public void after(JoinPoint joinPoint, Object value) {
        Result result = JSONObject.parseObject(JSONObject.toJSONString(value), Result.class);
        saveLog(joinPoint, SUCCESS, "登录成功");
    }

    private void saveLog(JoinPoint joinPoint, String flat, Object data) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation annotation = method.getAnnotation(ApiOperation.class);
        SysLoginLog sysLoginLog = new SysLoginLog();
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Object[] args = joinPoint.getArgs();
        if(ObjectUtils.isNotEmpty(args)){
            SysUser user  = (SysUser) args[0];
            sysLoginLog.setCreateUserName(user.getUserName());
        }
        String remoteAddr = request.getRemoteAddr();
        if (Arrays.asList(IPS).contains(remoteAddr)) {
            sysLoginLog.setAddress("本地");
        } else {
            Map<String, String> map = new HashMap<>(8);
            map.put("ak", "");
            map.put("ip", remoteAddr);
            map.put("coor", "bd09ll");
            JSONObject object = restTemplate.getForObject(IPAPI, JSONObject.class, map);
            if (object != null && "0".equals(object.getString("status"))) {
                JSONObject content = object.getJSONObject("content");
                sysLoginLog.setAddress(content.getString("address"));
            }
        }
        sysLoginLog.setId(IdGeneratorUtil.incrementId())
                .setState(flat)
                .setIpAddress(request.getRemoteAddr())
                .setCreateTime(LocalDateTime.now())
                .setClient(userAgent.getBrowser().getName())
                .setSysName(userAgent.getOperatingSystem().getName())
                .setRsres(data.toString());
        try {
            kafkaTemplate.send("sys-login", JSONObject.toJSONString(sysLoginLog));
        } catch (Exception e) {
            log.error("kafka生产异常:", e);
        }
    }
}
